package parser;

import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import model.Conta;

public class ContaParser implements ContaTokens {
    private int yyss = 100;
    private int yytok;
    private int yysp = 0;
    private int[] yyst;
    protected int yyerrno = (-1);
    private Object[] yysv;
    private Object yyrv;

    public boolean parse() {
        int yyn = 0;
        yysp = 0;
        yyst = new int[yyss];
        yysv = new Object[yyss];
        yytok = (tokenType
                 );
    loop:
        for (;;) {
            switch (yyn) {
                case 0:
                    yyst[yysp] = 0;
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 18:
                    switch (yytok) {
                        case PALAVRA:
                            yyn = 5;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 1:
                    yyst[yysp] = 1;
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 19:
                    switch (yytok) {
                        case ENDINPUT:
                            yyn = 36;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 2:
                    yyst[yysp] = 2;
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 20:
                    switch (yytok) {
                        case ENDINPUT:
                        case PALAVRA:
                            yyn = yyr2();
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 3:
                    yyst[yysp] = 3;
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 21:
                    switch (yytok) {
                        case PALAVRA:
                            yyn = 5;
                            continue;
                        case ENDINPUT:
                            yyn = yyr1();
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 4:
                    yyst[yysp] = 4;
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 22:
                    switch (yytok) {
                        case PALAVRA:
                            yyn = 7;
                            continue;
                        case SEPARADOR:
                            yyn = 8;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 5:
                    yyst[yysp] = 5;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 23:
                    switch (yytok) {
                        case SEPARADOR:
                        case PALAVRA:
                            yyn = yyr5();
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 6:
                    yyst[yysp] = 6;
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 24:
                    switch (yytok) {
                        case ENDINPUT:
                        case PALAVRA:
                            yyn = yyr3();
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 7:
                    yyst[yysp] = 7;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 25:
                    switch (yytok) {
                        case SEPARADOR:
                        case PALAVRA:
                            yyn = yyr6();
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 8:
                    yyst[yysp] = 8;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 26:
                    switch (yytok) {
                        case NUMERO:
                            yyn = 9;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 9:
                    yyst[yysp] = 9;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 27:
                    switch (yytok) {
                        case SEPARADOR:
                            yyn = 10;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 10:
                    yyst[yysp] = 10;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 28:
                    switch (yytok) {
                        case NUMERO:
                            yyn = 11;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 11:
                    yyst[yysp] = 11;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 29:
                    switch (yytok) {
                        case VIRGULA:
                            yyn = 12;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 12:
                    yyst[yysp] = 12;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 30:
                    switch (yytok) {
                        case NUMERO:
                            yyn = 13;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 13:
                    yyst[yysp] = 13;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 31:
                    switch (yytok) {
                        case SEPARADOR:
                            yyn = 14;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 14:
                    yyst[yysp] = 14;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 32:
                    switch (yytok) {
                        case NUMERO:
                            yyn = 15;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 15:
                    yyst[yysp] = 15;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 33:
                    switch (yytok) {
                        case VIRGULA:
                            yyn = 16;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 16:
                    yyst[yysp] = 16;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 34:
                    switch (yytok) {
                        case NUMERO:
                            yyn = 17;
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 17:
                    yyst[yysp] = 17;
                    yysv[yysp] = (tokenVal
                                 );
                    yytok = (getToken()
                            );
                    if (++yysp>=yyst.length) {
                        yyexpand();
                    }
                case 35:
                    switch (yytok) {
                        case ENDINPUT:
                        case PALAVRA:
                            yyn = yyr4();
                            continue;
                    }
                    yyn = 39;
                    continue;

                case 36:
                    return true;
                case 37:
                    yyerror("stack overflow");
                case 38:
                    return false;
                case 39:
                    yyerror("syntax error");
                    return false;
            }
        }
    }

    protected void yyexpand() {
        int[] newyyst = new int[2*yyst.length];
        Object[] newyysv = new Object[2*yyst.length];
        for (int i=0; i<yyst.length; i++) {
            newyyst[i] = yyst[i];
            newyysv[i] = yysv[i];
        }
        yyst = newyyst;
        yysv = newyysv;
    }

    private int yyr1() { // arquivo : conta_seq
        { output = (List<Conta>)yysv[yysp-1]; }
        yysv[yysp-=1] = yyrv;
        return 1;
    }

    private int yyr4() { // conta : palavra_seq SEPARADOR NUMERO SEPARADOR NUMERO VIRGULA NUMERO SEPARADOR NUMERO VIRGULA NUMERO
        { yyrv = new Conta(returnName((List<String>)yysv[yysp-11]), (String)yysv[yysp-9], Integer.parseInt((String)yysv[yysp-7]), Integer.parseInt((String)yysv[yysp-5]), Integer.parseInt((String)yysv[yysp-3]), Integer.parseInt((String)yysv[yysp-1])); }
        yysv[yysp-=11] = yyrv;
        switch (yyst[yysp-1]) {
            case 0: return 2;
            default: return 6;
        }
    }

    private int yyr2() { // conta_seq : conta
        { List<Conta> contas = new ArrayList<Conta>();
                                                                          contas.add((Conta)yysv[yysp-1]);
                                                                          yyrv = contas; }
        yysv[yysp-=1] = yyrv;
        return 3;
    }

    private int yyr3() { // conta_seq : conta_seq conta
        { List<Conta> contas = (List<Conta>)yysv[yysp-2];
                                                                          contas.add((Conta)yysv[yysp-1]);
                                                                          yyrv = contas; }
        yysv[yysp-=2] = yyrv;
        return 3;
    }

    private int yyr5() { // palavra_seq : PALAVRA
        { List<String> palavras = new ArrayList<String>();
                                                                          palavras.add((String)yysv[yysp-1]);
                                                                          yyrv = palavras;}
        yysv[yysp-=1] = yyrv;
        return 4;
    }

    private int yyr6() { // palavra_seq : palavra_seq PALAVRA
        { List<String> palavras = (List<String>)yysv[yysp-2];
                                                                          palavras.add((String)yysv[yysp-1]);
                                                                          yyrv = palavras;}
        yysv[yysp-=2] = yyrv;
        return 4;
    }

    protected String[] yyerrmsgs = {
    };


int tokenType;
String tokenVal;
ContaScanner scanner;
public List<Conta> output;

public ContaParser(Reader input) {
    scanner = new ContaScanner(input);
    getToken();
}

int getToken() {
    try {
            ContaToken tok = scanner.getToken();
                if(tok != null) {
                        tokenType = tok.type;
                        tokenVal = tok.toString();
                        return tokenType;
                }
                return 0;
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
}

String returnName(List<String> list) {
        StringBuilder sb = new StringBuilder();
        
        for(String s : list) {
                sb.append(s + " ");
        }
        
        return sb.toString().trim();    
}

void yyerror(String msg) {
    throw new RuntimeException(msg);
}

}
